Underfitting and Overfitting
在这一步结束时,你将理解欠拟合和过拟合的概念,并能够将这些理念应用到使你的模型更准确
Experimenting With Different Models
既然你已经有了可靠的方法来衡量模型的准确性,你就可以尝试不同的模型,看看哪个能提供最佳的预测。但是,你有哪些模型的替代选项呢?
你可以在scikit-learn的文档中看到,决策树模型有很多选项(比你长时间需要的还要多)。最重要的选项决定了树的深度。回想一下本课程的第一课,树的深度是衡量它在做出预测之前进行多少次分割的指标。这是一个相对较浅的树。
在实践中,一棵树在顶层(所有房屋)和叶子节点之间有10次分割并不罕见。随着树变得更深,数据集被切割成包含更少房屋的叶子。如果一棵树只有1次分割,它会将数据分成2组。如果每组再次分割,我们将得到4组房屋。再次分割这些组将创建8组。如果我们通过在每个级别添加更多分割来持续将组数翻倍,到第10级时我们将有[2^{10}]组房屋。那是1024个叶子。
当我们将房屋分配给许多叶子时,每个叶子中的房屋数量也会减少。叶子中房屋很少将使得预测值非常接近这些房屋的实际值,但它们可能对新数据做出非常不可靠的预测(因为每个预测仅基于少数房屋)。
这是一种称为**overfitting(过拟合)**的现象,模型几乎完美地匹配训练数据,但在验证和其他新数据上表现不佳。另一方面,如果我们使树非常浅,它就不会将房屋分成非常不同的组。
在极端情况下,如果一棵树只将房屋分成2或4组,每个组仍然有各种各样的房屋。对于大多数房屋来说,结果预测可能相差很远,即使在训练数据中也是如此(出于同样的原因,在验证中也会很糟糕)。当模型未能捕捉数据中的重要区别和模式,以至于即使在训练数据上也表现不佳时,这被称为underfitting(欠拟合)。
由于我们关心新数据的准确性,我们从验证数据中估计这一点,我们希望在欠拟合和过拟合之间找到最佳点。在下面的图表中,我们希望找到(红色)验证曲线的最低点。
Example
控制树的深度有几种替代方法,许多方法允许树中的某些路径比其他路径更深。但是,max_leaf_nodes
参数提供了一种非常合理的控制过拟合与欠拟合的方法。我们允许模型创建的叶子越多,我们就越多地从上述图表中的欠拟合区域移动到过拟合区域。
我们可以使用一个效用函数(utility function)来帮助比较不同max_leaf_nodes
值的MAE(平均绝对误差)得分:
from sklearn.metrics import mean_absolute_error
from sklearn.tree import DecisionTreeRegressor
def get_mae(max_leaf_nodes, train_X, val_X, train_y, val_y):
model = DecisionTreeRegressor(max_leaf_nodes=max_leaf_nodes, random_state=0)
model.fit(train_X, train_y)
preds_val = model.predict(val_X)
mae = mean_absolute_error(val_y, preds_val)
return(mae)
使用您已经看到(并且已经编写过)的代码将数据加载到train_X、val_X、train_y和val_y中。
# Data Loading Code Runs At This Point
import pandas as pd
# Load data
melbourne_file_path = '../input/melbourne-housing-snapshot/melb_data.csv'
melbourne_data = pd.read_csv(melbourne_file_path)
# Filter rows with missing values
filtered_melbourne_data = melbourne_data.dropna(axis=0)
# Choose target and features
y = filtered_melbourne_data.Price
melbourne_features = ['Rooms', 'Bathroom', 'Landsize', 'BuildingArea',
'YearBuilt', 'Lattitude', 'Longtitude']
X = filtered_melbourne_data[melbourne_features]
from sklearn.model_selection import train_test_split
# split data into training and validation data, for both features and target
train_X, val_X, train_y, val_y = train_test_split(X, y,random_state = 0)
我们可以使用for循环来比较使用max_leaf_nodes的不同值构建的模型的准确性。
# compare MAE with differing values of max_leaf_nodes
for max_leaf_nodes in [5, 50, 500, 5000]:
my_mae = get_mae(max_leaf_nodes, train_X, val_X, train_y, val_y)
print("Max leaf nodes: %d \t\t Mean Absolute Error: %d" %(max_leaf_nodes, my_mae))
Max leaf nodes: 5 Mean Absolute Error: 347380
Max leaf nodes: 50 Mean Absolute Error: 258171
Max leaf nodes: 500 Mean Absolute Error: 243495
Max leaf nodes: 5000 Mean Absolute Error: 254983
在列出的选项中,500是叶子的最优数量。
Conclusion
结论是:模型可能会有以下两种情况:
- 过度拟合:捕捉未来不会再出现的虚假模式,导致预测不太准确,或者
- 拟合不足:未能捕捉相关模式,再次导致预测不太准确。
我们使用模型训练中没有使用的验证数据来衡量候选模型的准确性。这让我们可以尝试许多候选模型,并保留最好的模型。
Exercise
Recap
回顾一下本课程之前书写的代码
# Code you have previously used to load data
import pandas as pd
from sklearn.metrics import mean_absolute_error
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeRegressor
# Path of the file to read
iowa_file_path = '../input/home-data-for-ml-course/train.csv'
home_data = pd.read_csv(iowa_file_path)
# Create target object and call it y
y = home_data.SalePrice
# Create X
features = ['LotArea', 'YearBuilt', '1stFlrSF', '2ndFlrSF', 'FullBath', 'BedroomAbvGr', 'TotRmsAbvGrd']
X = home_data[features]
# Split into validation and training data
train_X, val_X, train_y, val_y = train_test_split(X, y, random_state=1)
# Specify Model
iowa_model = DecisionTreeRegressor(random_state=1)
# Fit Model
iowa_model.fit(train_X, train_y)
# Make validation predictions and calculate mean absolute error
val_predictions = iowa_model.predict(val_X)
val_mae = mean_absolute_error(val_predictions, val_y)
print("Validation MAE: {:,.0f}".format(val_mae))
# Set up code checking
from learntools.core import binder
binder.bind(globals())
from learntools.machine_learning.ex5 import *
print("\nSetup complete")
你可以自己编写函数’ get_mae ‘。目前,我们将提供它。这和你在上一课读到的函数是一样的。运行下面的单元格。
def get_mae(max_leaf_nodes, train_X, val_X, train_y, val_y):
model = DecisionTreeRegressor(max_leaf_nodes=max_leaf_nodes, random_state=0)
model.fit(train_X, train_y)
preds_val = model.predict(val_X)
mae = mean_absolute_error(val_y, preds_val)
return(mae)
Step 1: Compare Different Tree Sizes
编写一个循环,从一组可能的值中为max_leaf_nodes尝试以下值。
对max_leaf_nodes的每个值调用get_mae函数。以一种允许您选择max_leaf_nodes的值的方式存储输出,该值给出数据的最准确模型。
candidate_max_leaf_nodes = [5, 25, 50, 100, 250, 500]
# Write loop to find the ideal tree size from candidate_max_leaf_nodes
my_mae = {leaf_size:get_mae(leaf_size,train_X,val_X,train_y,val_y) for leaf_size in candidate_max_leaf_nodes}
# Store the best value of max_leaf_nodes (it will be either 5, 25, 50, 100, 250 or 500)
best_tree_size = min(my_mae,key = my_mae.get)
# Check your answer
step_1.check()
Step 2: Fit Model Using All Data
你知道最好的树的大小。如果您打算在实践中部署此模型,则可以通过使用所有数据并保持该树的大小来使其更加准确。也就是说,既然您已经做出了所有的建模决策,就不需要再提供验证数据了。
# Fill in argument to make optimal size and uncomment
final_model = DecisionTreeRegressor(max_leaf_nodes=best_tree_size,random_state=1)
# fit the final model and uncomment the next two lines
final_model.fit(X, y)
# Check your answer
step_2.check()